package com.kaikeba.estack.web.filter;

import com.kaikeba.estack.web.ApplicationContext;
import com.kaikeba.estack.web.SecurityFacade;
import com.kaikeba.estack.web.constant.WebConstant;
import org.apache.commons.lang3.StringUtils;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.*;

public class AccessControlFilter implements Filter {

    private static final String IGNORE_URL_REGEX_KEY = "ignoreUrl";


    private static final Set<String> NOT_PROTECTED_URLS = new HashSet<>();


    private EnumMap<WebConstant.Platform, String> PLATFORM_LOGIN_URL_MAP = null;

    @Override
    public void init(FilterConfig config) throws ServletException {

        String adminLoginUrl = ApplicationContext.getApplicationConfigByKey(WebConstant.ADMIN_LOGIN_PAGE_URL_KEY, String.class);
        String phoneLoginUrl = ApplicationContext.getApplicationConfigByKey(WebConstant.PHONE_LOGIN_PAGE_URL_KEY, String.class);
        Map<WebConstant.Platform, String> loginUrlMap = new LinkedHashMap<>();
        if (StringUtils.isNotBlank(adminLoginUrl)) {
            NOT_PROTECTED_URLS.add(adminLoginUrl);
            loginUrlMap.put(WebConstant.Platform.WEB, adminLoginUrl);
        }
        if (StringUtils.isNotBlank(phoneLoginUrl)) {
            NOT_PROTECTED_URLS.add(phoneLoginUrl);
            loginUrlMap.put(WebConstant.Platform.IOS, phoneLoginUrl);
            loginUrlMap.put(WebConstant.Platform.ANDROID, phoneLoginUrl);
        }
        PLATFORM_LOGIN_URL_MAP = new EnumMap<>(loginUrlMap);
        String ignoreLoginUrls = ApplicationContext.getApplicationConfigByKey(WebConstant.LOGIN_IGNORE_PAGE_URL_KEY, String.class);
        //将需要登录忽略的url地址放入到set中
        Arrays.stream(StringUtils.split(ignoreLoginUrls, ","))
                .filter(StringUtils::isNotBlank)
                .forEach(NOT_PROTECTED_URLS::add);
    }


    @Override
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) resp;
        //1.    获取用户请求的uri   /xx.do
        String requestURL = request.getRequestURI();
        String contextPath = request.getContextPath();
        if (!"/".equals(contextPath)) {
            requestURL = requestURL.substring(contextPath.length());
            //requestURL:/backend/aa.do
        }
        String suffixUrl = requestURL.substring(requestURL.lastIndexOf("/"));
        if (!suffixUrl.contains(".") || suffixUrl.endsWith(".html")) {
            boolean isLogin = checkLogin(request, response, requestURL);
            //如果在未登录的情况下需要跳转到登录页
            if (!isLogin) {
                response.sendRedirect(request.getContextPath() + this.getLoginUrl(request));
                return;
            }
        }
        chain.doFilter(request, response);
    }

    /**
     * 根据当前请求获取是web端还是手端
     *
     * @param request
     * @return
     */
    private String getLoginUrl(HttpServletRequest request) {
        String userAgent = request.getHeader("user-agent");
        return PLATFORM_LOGIN_URL_MAP.get(WebConstant.Platform.getPlatform(userAgent));
    }


    /**
     * 校验用户是否登录
     *
     * @param request
     * @param response
     * @return
     */
    private boolean checkLogin(HttpServletRequest request, HttpServletResponse response, String requestUrl) {
        //如果是登录页则放行
        if (NOT_PROTECTED_URLS.contains(requestUrl)) {
            return true;
        }
        //用户如果在登录
        return SecurityFacade.getCurrentUser() != null;
    }

    @Override
    public void destroy() {
    }

}
